<!DOCTYPE html>
<html>
  <!-- meta/link... -->
  



<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <!-- Global site tag (gtag.js) - Google Analytics -->


  <title>archives: 2024/4 | ITBlog</title>

  <link rel="icon" type="image/x-icon, image/vnd.microsoft.icon" href="/itblog/favicon.ico">
  <link rel="stylesheet" href="https://at.alicdn.com/t/font_1911880_c1nvbyezg17.css">
  <link href="https://unpkg.com/@fortawesome/fontawesome-free/css/all.min.css" rel="stylesheet">
  <link href="/itblog/js/swiper/swiper@5.4.1.min.css" rel="stylesheet">
  
  
  
  
<link rel="stylesheet" href="/itblog/css/animate.min.css">

  
<link rel="stylesheet" href="/itblog/css/style.css">

  
  
    <link href="https://unpkg.com/@fancyapps/ui@5.0/dist/fancybox/fancybox.css" rel="stylesheet">
  
  
    
<link rel="stylesheet" href="/itblog/js/shareJs/share.min.css">

  
  <style>
        @media (max-width: 992px) {
            #waifu {
                display: none;
            }
        }
    </style>
    <script defer src="//cdn.bootcss.com/pace/1.0.2/pace.min.js"></script>
    <link href="//cdn.bootcss.com/pace/1.0.2/themes/pink/pace-theme-flash.css" rel="stylesheet">

    
    
    <!-- 依赖于jquery和vue -->
    <script src="https://unpkg.com/jquery@3.5.1/dist/jquery.min.js"></script>
    <script src="https://unpkg.com/vue@2.6.11/dist/vue.min.js"></script>

    <!-- import link -->
    
        
            
        
            
        
    
    <!-- import script -->
    
        
            
        
            
        
    

<meta name="generator" content="Hexo 7.1.1"><link rel="alternate" href="/itblog/atom.xml" title="ITBlog" type="application/atom+xml">
</head>

  
  <!-- 预加载动画 -->
  
  
  <div class="preloader_6" id="loader">
  <div class="loader"></div>
</div>
  <script>
    var endLoading = function () {
      document.body.style.overflow = 'auto';
      document.getElementById('loader').classList.add("loaded");
    }
    window.addEventListener('DOMContentLoaded', endLoading);
  </script>


  <body>
    <!-- 判断是否为暗黑风格 -->
    <!-- 判断是否为黑夜模式 -->
<script defer>
  let isDark = JSON.parse(localStorage.getItem('dark')) || JSON.parse('false');

  if (isDark) {
    $(document.body).addClass('darkModel');
  }
</script>

    <!-- 需要在上面加载的js -->
    <script>
  function loadScript(src, cb) {
    return new Promise(resolve => {
      setTimeout(function () {
        var HEAD = document.getElementsByTagName("head")[0] || document.documentElement;
        var script = document.createElement("script");
        script.setAttribute("type", "text/javascript");
        if (cb) {
          if (JSON.stringify(cb)) {
            for (let p in cb) {
              if (p == "onload") {
                script[p] = () => {
                  cb[p]()
                  resolve()
                }
              } else {
                script[p] = cb[p]
                script.onload = resolve
              }
            }
          } else {
            script.onload = () => {
              cb()
              resolve()
            };
          }
        } else {
          script.onload = resolve
        }
        script.setAttribute("src", src);
        HEAD.appendChild(script);
      });
    });
  }

  //https://github.com/filamentgroup/loadCSS
  var loadCSS = function (src) {
    return new Promise(resolve => {
      setTimeout(function () {
        var link = document.createElement('link');
        link.rel = "stylesheet";
        link.href = src;
        link.onload = resolve;
        document.getElementsByTagName("head")[0].appendChild(link);
      });
    });
  };

</script> 

<!-- 轮播图所需要的js -->
<script src="/itblog/js/swiper/swiper.min.js"></script>
<script src="/itblog/js/swiper/vue-awesome-swiper.js"></script>
<script src="/itblog/js/swiper/swiper.animate1.0.3.min.js"></script>

<script type="text/javascript">
  Vue.use(window.VueAwesomeSwiper)
</script>


  <script src="/itblog/js/vue-typed-js/index.js"></script>


<!-- 首页的公告滚动插件的js需要重新加载 -->
<script src="/itblog/js/vue-seamless-scroll/index.js"></script>

<!-- 打字机效果js -->
<script src="https://unpkg.com/typed.js@2.0.11"></script>


    <div id="safearea">
      <main class="main" id="pjax-container">
        <!-- 头部导航 -->
        
<header class="header  " 
  id="navHeader"
  style="position: fixed;
  left: 0; top: 0; z-index: 10;width: 100%;"
>
  <div class="header-content">
    <div class="bars">
      <div id="appDrawer" class="sidebar-image">
  <div class="drawer-box-icon">
    <i class="fas fa-bars" aria-hidden="true" @click="showDialogDrawer"></i>
  </div>
  
  <transition name="fade">
    <div class="drawer-box_mask" v-cloak style="display: none;" v-show="visible" @click.self="cancelDialogDrawer">
    </div>
  </transition>
  <div class="drawer-box" :class="{'active': visible}">
    <div class="drawer-box-head bg-color">
      <img class="drawer-box-head_logo lazyload placeholder" src="/itblog/medias/logo.png" class="lazyload placeholder" data-srcset="/itblog/medias/logo.png" srcset="https://pic1.zhimg.com/v2-cd38920285d125be80b3eb504052c550_b.webp" alt="logo">
      <h3 class="drawer-box-head_title">ITBlog</h3>
      <h5 class="drawer-box-head_desc"></h5>
    </div>
    
    <div class="drawer-box-content">
      <ul class="drawer-box-content_menu">
        
        
          <li class="drawer-box-content_item">
            <a target="_blank" rel="noopener" href="https://github.com/yuang01/hexo-theme-bamboo">
              <i class="fas fa-github" aria-hidden="true"></i>
              <span>Github</span>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</div>

<script>
  var body = document.body || document.documentElement || window;
  var vm = new Vue({
    el: '#appDrawer',
    data: {
      visible: false,
      top: 0,
      openArr: [],
    },
    computed: {
    },
    mounted() {
    },
    methods: {
      isOpen(index) {
        if (this.openArr.includes(index)) {
          return true;
        } else {
          return false;
        }
      },
      openOrCloseMenu(curIndex) {
        const index = this.openArr.indexOf(curIndex);
        if (index !== -1) {
          this.openArr.splice(index, 1);
        } else {
          this.openArr.push(curIndex);
        }
      },
      showDialogDrawer() {
        this.visible = true;
        // 防止页面滚动，只能让弹框滚动
        this.top = $(document).scrollTop()
        body.style.cssText = 'width: 100%; height: 100%;overflow: hidden;';
      },
      cancelDialogDrawer() {
        this.visible = false;
        body.removeAttribute('style');
        $(document).scrollTop(this.top)
      }
    },
    created() {}
  })
</script>

    </div>
    <div class="blog-title" id="author-avatar">
      
        <div class="avatar">
          <img src="/itblog/medias/logo.png" class="lazyload placeholder" data-srcset="/itblog/medias/logo.png" srcset="https://pic1.zhimg.com/v2-cd38920285d125be80b3eb504052c550_b.webp" alt="logo">
        </div>
      
      <a href="/itblog/" class="logo">ITBlog</a>
    </div>
    <nav class="navbar">
      <ul class="menu">
        
      </ul>
      
      
        <div id="appSearch">
  <div class="search"  @click="showDialog()"><i class="fas fa-search" aria-hidden="true"></i></div>
  <transition name="fade">
    <div class="message-box_wrapper" style="display: none;" v-cloak v-show="dialogVisible" @click.self="cancelDialogVisible()">
      <div class="message-box animated bounceInDown">
        <h2>
          <span>
            <i class="fas fa-search" aria-hidden="true"></i>
            <span class="title">Search</span>
          </span>
          <i class="fas fa-times close" pointer style="float:right;" aria-hidden="true" @click.self="cancelDialogVisible()"></i>
        </h2>
        <form class="site-search-form">
          <input type="text"
            placeholder="Please enter keywords"
            id="local-search-input" 
            @click="getSearchFile()"
            class="st-search-input"
            v-model="searchInput"
          />
        </form>
        <div class="result-wrapper">
          <div id="local-search-result" class="local-search-result-cls"></div>
        </div>
      </div>
    </div>
  </transition>
</div>
<script src="/itblog/js/local_search.js"></script>
<script>
  var body = document.body || document.documentElement || window;
  var vm = new Vue({
    el: '#appSearch',
    data: {
      dialogVisible: false,
      searchInput: '',
      top: 0,
    },
    computed: {
    },
    mounted() {
      window.addEventListener('pjax:complete', () => {
        this.cancelDialogVisible();
      })
    },
    methods: {
      showDialog() {
        this.dialogVisible = true;
        // 防止页面滚动，只能让弹框滚动
        this.top = $(document).scrollTop()
        body.style.cssText = 'overflow: hidden;';
      },
      getSearchFile() {
        if (!this.searchInput) {
          getSearchFile("/itblog/search.xml");
        }
      },
      cancelDialogVisible() {
        this.dialogVisible = false;
        body.removeAttribute('style');
        $(document).scrollTop(this.top)
      },
    },
    created() {}
  })
</script>
<!-- 解决刷新页面闪烁问题，可以在元素上添加display: none, 或者用vue.extend方法，详情：https://blog.csdn.net/qq_31393401/article/details/81017912 -->
<!-- 下面是搜索基本写法 -->
<!-- <script type="text/javascript" id="local.search.active">
  var inputArea = document.querySelector("#local-search-input");
  inputArea.onclick   = function(){ getSearchFile(); this.onclick = null }
  inputArea.onkeydown = function(){ if(event.keyCode == 13) return false }
</script> -->

      

    </nav>
  </div>
  
    <a target="_blank" rel="noopener" href="https://github.com/yuang01/hexo-theme-bamboo" class="github-corner color-primary" aria-label="View source on GitHub"><svg width="60" height="60" viewBox="0 0 250 250" style="fill:#fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style>
  
  
</header>
        <!-- 内容区域 -->
        <div class="bg-dark-floor" style="position: fixed;left: 0;top: 0;width: 100%;height: 100%;z-index: -2;"></div>
<div class="bg-light-floor-archive" style="position: fixed;left: 0;top: 0;width: 100%;height: 100%;z-index: -3;"></div>
<div class="archive-header" style="background-image:url('https://pic1.zhimg.com/80/v2-1414b3a4b205e19060db18a20d08723a_1440w.jpg?source=1940ef5c')">
  <div class="archive-header-title">
    archive
  </div>
  <div class="archive-header-desc">
  
  <span class="title" id="archive-header-desc"></span>
  <script>
  function typedFn() {
    const el = '#archive-header-desc';
    const type = 'archive';
    let desc = '愿你如风，被人温柔以待'
    var typed = new Typed(el, {
      strings: [desc],
      startDelay: 100,
      typeSpeed: 100,
      loop: true,
      backSpeed: 50,
      showCursor: true
    });
  }
  typedFn();
</script>
  
  </div>
  <div class="mask-box"></div>
</div>

<div class="archive-video">
  <video class="full-video" autoplay loop muted>
      <source style="width: 100%;height: 100vh;" src="/itblog/">
  </video>
  <div class="video-header-title">
    archive
  </div>
  <div class="video-header-desc">
  
      <span class="title" id="archive-video-header-desc"></span>
      <script>
  function typedFn() {
    const el = '#archive-video-header-desc';
    const type = 'archive';
    let desc = '愿你如风，被人温柔以待'
    var typed = new Typed(el, {
      strings: [desc],
      startDelay: 100,
      typeSpeed: 100,
      loop: true,
      backSpeed: 50,
      showCursor: true
    });
  }
  typedFn();
</script>
      
  </div>
  <div class="mask-box"></div>
</div>

<!-- hash算法 -->


<div class="archive-main">
  <section class="archive">
    <div class="archive-content">
      <ul class="post-archive">
        
        
          
            
            <div class="year" data-aos="zoom-in-up">
                <div class="bullet"></div>
                <a href="/itblog/archives/2024">2024</a>
            </div>
          
          <li class="post-item" data-aos="fade-left">
            
            <div class="post-img-box">
              <a href="/itblog/2024/04/01/%E6%90%AD%E5%BB%BA%E5%85%8D%E8%B4%B9%E5%8D%9A%E5%AE%A2/" class="post-img " style="background-size: cover; 
                background-position: center center;">
                <img class="lazyload lazyload placeholder" src="https://picx.zhimg.com/80/v2-b44931ea513e5f7b3b06f2703f79653c_1440w.webp" class="lazyload placeholder" data-srcset="https://picx.zhimg.com/80/v2-b44931ea513e5f7b3b06f2703f79653c_1440w.webp" srcset="https://pic1.zhimg.com/v2-cd38920285d125be80b3eb504052c550_b.webp" alt="">
              </a>
            </div>
            <div class="post-date-title">
              <div>
                <span class="post-date">04-01</span>
              </div>
              <a class="post-title" href="/itblog/2024/04/01/%E6%90%AD%E5%BB%BA%E5%85%8D%E8%B4%B9%E5%8D%9A%E5%AE%A2/">Hexo+gitee搭建免费博客</a>
            </div>
          </li>
        
          
          <li class="post-item" data-aos="fade-left">
            
            <div class="post-img-box">
              <a href="/itblog/2024/04/01/hello-world/" class="post-img " style="background-size: cover; 
                background-position: center center;">
                <img class="lazyload lazyload placeholder" src="https://pic3.zhimg.com/80/v2-5f7cb7e900b9dcf5354c3d4d2c5cc3c2_1440w.webp" class="lazyload placeholder" data-srcset="https://pic3.zhimg.com/80/v2-5f7cb7e900b9dcf5354c3d4d2c5cc3c2_1440w.webp" srcset="https://pic1.zhimg.com/v2-cd38920285d125be80b3eb504052c550_b.webp" alt="">
              </a>
            </div>
            <div class="post-date-title">
              <div>
                <span class="post-date">04-01</span>
              </div>
              <a class="post-title" href="/itblog/2024/04/01/hello-world/">Hello World</a>
            </div>
          </li>
        
      </ul>
    </div>
  </section>
  <div class="w-70">
    
  </div>
</div>

      </main>
    </div>

    <!-- 页脚 -->
    
  
  
    <!-- 底部鱼儿跳动效果，依赖于jquery-->
<div id="j-fish-skip" style=" position: relative;height: 153px;width: auto;"></div>
<script defer>
  var RENDERER = {
    POINT_INTERVAL: 5,
    FISH_COUNT: 3,
    MAX_INTERVAL_COUNT: 50,
    INIT_HEIGHT_RATE: .5,
    THRESHOLD: 50,
    FISH_COLOR: '',
    init: function () {
      this.setFishColor(); this.setParameters(), this.reconstructMethods(), this.setup(), this.bindEvent(), this.render()
    },
    setFishColor: function () {
      let isDark = JSON.parse(localStorage.getItem('dark')) || JSON.parse('false');
      if (isDark) {
        this.FISH_COLOR = '#222'; // 暗黑色，有时间把这整成一个变量
      } else {
        this.FISH_COLOR = '' || 'rgba(66, 185, 133, 0.8)';
      }
    },
    setParameters: function () {
      this.$window = $(window), this.$container = $("#j-fish-skip"), this.$canvas = $("<canvas />"), this.context = this.$canvas.appendTo(this.$container).get(0).getContext("2d"), this.points = [], this.fishes = [], this.watchIds = []
    },
    createSurfacePoints: function () {
      var t = Math.round(this.width / this.POINT_INTERVAL);
      this.pointInterval = this.width / (t - 1), this.points.push(new SURFACE_POINT(this, 0));
      for (var i = 1; i < t; i++) {
        var e = new SURFACE_POINT(this, i * this.pointInterval),
          h = this.points[i - 1];
        e.setPreviousPoint(h), h.setNextPoint(e), this.points.push(e)
      }
    },
    reconstructMethods: function () {
      this.watchWindowSize = this.watchWindowSize.bind(this), this.jdugeToStopResize = this.jdugeToStopResize.bind(this), this.startEpicenter = this.startEpicenter.bind(this), this.moveEpicenter = this.moveEpicenter.bind(this), this.reverseVertical = this.reverseVertical.bind(this), this.render = this.render.bind(this)
    },
    setup: function () {
      this.points.length = 0, this.fishes.length = 0, this.watchIds.length = 0, this.intervalCount = this.MAX_INTERVAL_COUNT, this.width = this.$container.width(), this.height = this.$container.height(), this.fishCount = this.FISH_COUNT * this.width / 500 * this.height / 500, this.$canvas.attr({
        width: this.width,
        height: this.height
      }), this.reverse = !1, this.fishes.push(new FISH(this)), this.createSurfacePoints()
    },
    watchWindowSize: function () {
      this.clearTimer(), this.tmpWidth = this.$window.width(), this.tmpHeight = this.$window.height(), this.watchIds.push(setTimeout(this.jdugeToStopResize, this.WATCH_INTERVAL))
    },
    clearTimer: function () {
      for (; this.watchIds.length > 0;) clearTimeout(this.watchIds.pop())
    },
    jdugeToStopResize: function () {
      var t = this.$window.width(),
        i = this.$window.height(),
        e = t == this.tmpWidth && i == this.tmpHeight;
      this.tmpWidth = t, this.tmpHeight = i, e && this.setup()
    },
    bindEvent: function () {
      this.$window.on("resize", this.watchWindowSize), this.$container.on("mouseenter", this.startEpicenter), this.$container.on("mousemove", this.moveEpicenter)
    },
    getAxis: function (t) {
      var i = this.$container.offset();
      return {
        x: t.clientX - i.left + this.$window.scrollLeft(),
        y: t.clientY - i.top + this.$window.scrollTop()
      }
    },
    startEpicenter: function (t) {
      this.axis = this.getAxis(t)
    },
    moveEpicenter: function (t) {
      var i = this.getAxis(t);
      this.axis || (this.axis = i), this.generateEpicenter(i.x, i.y, i.y - this.axis.y), this.axis = i
    },
    generateEpicenter: function (t, i, e) {
      if (!(i < this.height / 2 - this.THRESHOLD || i > this.height / 2 + this.THRESHOLD)) {
        var h = Math.round(t / this.pointInterval);
        h < 0 || h >= this.points.length || this.points[h].interfere(i, e)
      }
    },
    reverseVertical: function () {
      this.reverse = !this.reverse;
      for (var t = 0, i = this.fishes.length; t < i; t++) this.fishes[t].reverseVertical()
    },
    controlStatus: function () {
      for (var t = 0, i = this.points.length; t < i; t++) this.points[t].updateSelf();
      for (t = 0, i = this.points.length; t < i; t++) this.points[t].updateNeighbors();
      this.fishes.length < this.fishCount && 0 == --this.intervalCount && (this.intervalCount = this.MAX_INTERVAL_COUNT, this.fishes.push(new FISH(this)))
    },
    render: function () {
      requestAnimationFrame(this.render), this.controlStatus(), this.context.clearRect(0, 0, this.width, this.height), this.context.fillStyle = this.FISH_COLOR;
      for (var t = 0, i = this.fishes.length; t < i; t++) this.fishes[t].render(this.context);
      this.context.save(), this.context.globalCompositeOperation = "xor", this.context.beginPath(), this.context.moveTo(0, this.reverse ? 0 : this.height);
      for (t = 0, i = this.points.length; t < i; t++) this.points[t].render(this.context);
      this.context.lineTo(this.width, this.reverse ? 0 : this.height), this.context.closePath(), this.context.fill(), this.context.restore()
    }
  },
  SURFACE_POINT = function (t, i) {
    this.renderer = t, this.x = i, this.init()
  };
  SURFACE_POINT.prototype = {
    SPRING_CONSTANT: .03,
    SPRING_FRICTION: .9,
    WAVE_SPREAD: .3,
    ACCELARATION_RATE: .01,
    init: function () {
      this.initHeight = this.renderer.height * this.renderer.INIT_HEIGHT_RATE, this.height = this.initHeight, this.fy = 0, this.force = {
        previous: 0,
        next: 0
      }
    },
    setPreviousPoint: function (t) {
      this.previous = t
    },
    setNextPoint: function (t) {
      this.next = t
    },
    interfere: function (t, i) {
      this.fy = this.renderer.height * this.ACCELARATION_RATE * (this.renderer.height - this.height - t >= 0 ? -1 : 1) * Math.abs(i)
    },
    updateSelf: function () {
      this.fy += this.SPRING_CONSTANT * (this.initHeight - this.height), this.fy *= this.SPRING_FRICTION, this.height += this.fy
    },
    updateNeighbors: function () {
      this.previous && (this.force.previous = this.WAVE_SPREAD * (this.height - this.previous.height)), this.next && (this.force.next = this.WAVE_SPREAD * (this.height - this.next.height))
    },
    render: function (t) {
      this.previous && (this.previous.height += this.force.previous, this.previous.fy += this.force.previous), this.next && (this.next.height += this.force.next, this.next.fy += this.force.next), t.lineTo(this.x, this.renderer.height - this.height)
    }
  };
  var FISH = function (t) {
    this.renderer = t, this.init()
  };
  FISH.prototype = {
    GRAVITY: .4,
    init: function () {
      this.direction = Math.random() < .5, this.x = this.direction ? this.renderer.width + this.renderer.THRESHOLD : -this.renderer.THRESHOLD, this.previousY = this.y, this.vx = this.getRandomValue(4, 10) * (this.direction ? -1 : 1), this.renderer.reverse ? (this.y = this.getRandomValue(1 * this.renderer.height / 10, 4 * this.renderer.height / 10), this.vy = this.getRandomValue(2, 5), this.ay = this.getRandomValue(.05, .2)) : (this.y = this.getRandomValue(6 * this.renderer.height / 10, 9 * this.renderer.height / 10), this.vy = this.getRandomValue(-5, -2), this.ay = this.getRandomValue(-.2, -.05)), this.isOut = !1, this.theta = 0, this.phi = 0
    },
    getRandomValue: function (t, i) {
      return t + (i - t) * Math.random()
    },
    reverseVertical: function () {
      this.isOut = !this.isOut, this.ay *= -1
    },
    controlStatus: function (t) {
      this.previousY = this.y, this.x += this.vx, this.y += this.vy, this.vy += this.ay, this.renderer.reverse ? this.y > this.renderer.height * this.renderer.INIT_HEIGHT_RATE ? (this.vy -= this.GRAVITY, this.isOut = !0) : (this.isOut && (this.ay = this.getRandomValue(.05, .2)), this.isOut = !1) : this.y < this.renderer.height * this.renderer.INIT_HEIGHT_RATE ? (this.vy += this.GRAVITY, this.isOut = !0) : (this.isOut && (this.ay = this.getRandomValue(-.2, -.05)), this.isOut = !1), this.isOut || (this.theta += Math.PI / 20, this.theta %= 2 * Math.PI, this.phi += Math.PI / 30, this.phi %= 2 * Math.PI), this.renderer.generateEpicenter(this.x + (this.direction ? -1 : 1) * this.renderer.THRESHOLD, this.y, this.y - this.previousY), (this.vx > 0 && this.x > this.renderer.width + this.renderer.THRESHOLD || this.vx < 0 && this.x < -this.renderer.THRESHOLD) && this.init()
    },
    render: function (t) {
      t.save(), t.translate(this.x, this.y), t.rotate(Math.PI + Math.atan2(this.vy, this.vx)), t.scale(1, this.direction ? 1 : -1), t.beginPath(), t.moveTo(-30, 0), t.bezierCurveTo(-20, 15, 15, 10, 40, 0), t.bezierCurveTo(15, -10, -20, -15, -30, 0), t.fill(), t.save(), t.translate(40, 0), t.scale(.9 + .2 * Math.sin(this.theta), 1), t.beginPath(), t.moveTo(0, 0), t.quadraticCurveTo(5, 10, 20, 8), t.quadraticCurveTo(12, 5, 10, 0), t.quadraticCurveTo(12, -5, 20, -8), t.quadraticCurveTo(5, -10, 0, 0), t.fill(), t.restore(), t.save(), t.translate(-3, 0), t.rotate((Math.PI / 3 + Math.PI / 10 * Math.sin(this.phi)) * (this.renderer.reverse ? -1 : 1)), t.beginPath(), this.renderer.reverse ? (t.moveTo(5, 0), t.bezierCurveTo(10, 10, 10, 30, 0, 40), t.bezierCurveTo(-12, 25, -8, 10, 0, 0)) : (t.moveTo(-5, 0), t.bezierCurveTo(-10, -10, -10, -30, 0, -40), t.bezierCurveTo(12, -25, 8, -10, 0, 0)), t.closePath(), t.fill(), t.restore(), t.restore(), this.controlStatus(t)
    }
  }, $(function () {
    RENDERER.init()
    $('.dark').click(function () {
      setTimeout(() => {
        RENDERER.setFishColor();
        RENDERER.context.fill();
      });
    })
  });
</script>
  
  <div class="footer bg-color">
    <div class="footer-main">
      
        
          <div class="link">
            
          </div>
        
      
        
          <div class="footer-copyright">
            <p>Copyright © 2019 - 2020 <a target="_blank" rel="noopener" href="https://github.com/yuang01">yuang01</a> | Powered by <a target="_blank" rel="noopener" href="https://hexo.io/zh-cn/docs/">Hexo</a> | Theme <a target="_blank" rel="noopener" href="https://github.com/yuang01/theme">Bamboo</a> </p>

          </div>
        
      
        
          <div class="footer-custom">
            
          </div>
        
      
    </div>
  </div>



    <!-- 渲染暗黑按钮 -->
    
      <div class="dark" onclick="toggleDarkMode()">
  <div class="dark-content">
    <i class="fas" id="darkIcon" aria-hidden="true"></i>
  </div>
</div>

<script defer>
  $(function() {
    // 初始化暗黑模式状态
    let isDark = JSON.parse(localStorage.getItem('dark')) || JSON.parse('false');
    updateDarkModeIcon(isDark);
  });

  function toggleDarkMode() {
    const isDark = $(document.body).hasClass('darkModel');
    $(document.body).toggleClass('darkModel');
    localStorage.setItem('dark', !isDark);
    updateDarkModeIcon(!isDark);
  }

  function updateDarkModeIcon(isDark) {
    const iconElement = document.getElementById('darkIcon');
    if (isDark) {
      iconElement.classList.remove('fa-moon');
      iconElement.classList.add('fa-lightbulb');
    } else {
      iconElement.classList.remove('fa-lightbulb');
      iconElement.classList.add('fa-moon');
    }
  }
</script>

    
    <!-- 渲染回到顶部按钮 -->
    
      <div class="goTop top-btn-color" pointer>
  <i class="fas fa-arrow-up" aria-hidden="true"></i>
</div>
<script defer src="/itblog/js/goTop.js"></script>

    
    <!-- 渲染左下角音乐播放器 -->
    

    <!-- 图片放大 -->
    
      <script src="https://unpkg.com/@fancyapps/ui@5.0/dist/fancybox/fancybox.umd.js"></script>
    

    <!-- 百度解析 -->
    <!-- Baidu Analytics -->

    <!-- Baidu Push -->

<script async>
    (function () {
        var bp = document.createElement('script');
        var curProtocol = window.location.protocol.split(':')[0];
        if (curProtocol === 'https') {
            bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
        } else {
            bp.src = 'http://push.zhanzhang.baidu.com/push.js';
        }
        var s = document.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(bp, s);
    })();
</script>

    
    <!-- 背景彩带 -->
    
      <script async type="text/javascript" size="100" alpha='0.4' zIndex="-1" src="/itblog/js/ribbon.min.js"></script>
    

    <script src="/itblog/js/utils/index.js"></script>
    <script src="/itblog/js/app.js"></script>
    
    <!-- 文章目录所需js -->
<!-- <link href="/itblog/js/tocbot/tocbot.css" rel="stylesheet">
<script src="/itblog/js/tocbot/tocbot.min.js"></script> -->

<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.18.2/tocbot.min.js"></script>


<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.18.2/tocbot.css">

<script>
  var headerEl = 'h2, h3, h4',  //headers 
    content = '.post-detail',//文章容器
    idArr = {};  //标题数组以确定是否增加索引id
  //add #id
  var option = {
    // Where to render the table of contents.
    tocSelector: '.toc',
    // Where to grab the headings to build the table of contents.
    contentSelector: content,
    // Which headings to grab inside of the contentSelector element.
    headingSelector: headerEl,
    scrollSmooth: true,
    scrollSmoothOffset: -70,
    // headingsOffset: -($(window).height() * 0.4 - 45),
    headingsOffset: -($(window).height() * 0.4 - 70),
    // positionFixedSelector: '.toc-main',
    // positionFixedClass: 'is-position-fixed',
    fixedSidebarOffset: 'auto',
    activeLinkClass: 'is-active-link',
    orderedList: true,
    collapseDepth: 20,
    // onClick: function (e) {},
  }
  if ($('.toc').length > 0) {

    $(content).children(headerEl).each(function () {
      //去除空格以及多余标点
      var headerId = $(this).text().replace(/[\s|\~|`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\_|\+|\=|\||\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?|\：|\，|\。]/g, '');

      headerId = headerId.toLowerCase();
      if (idArr[headerId]) {
        //id已经存在
        $(this).attr('id', headerId + '-' + idArr[headerId]);
        idArr[headerId]++;
      }
      else {
        //id未存在
        idArr[headerId] = 1;
        $(this).attr('id', headerId);
      }
    });

    document.addEventListener("DOMContentLoaded", function () {
      tocbot.init(option);
      mobileTocClick();
    });

  }

  window.tocScrollFn = function () {
    return bamboo.throttle(function () {
      findHeadPosition();
    }, 100)()
  }
  window.addEventListener('scroll', tocScrollFn);

  const findHeadPosition = function (top) {
    if ($('.toc-list').length <= 0) {
      return false;
    }
    setTimeout(() => {  // or DOMContentLoaded 
      autoScrollToc();
    }, 0);
  }

  const autoScrollToc = function () {
    const $activeItem = document.querySelector('.is-active-link');
    const $cardToc = document.querySelector('.toc-content');
    const activePosition = $activeItem.getBoundingClientRect().top
    const sidebarScrollTop = $cardToc.scrollTop
    if (activePosition > (document.documentElement.clientHeight - 100)) {
      $cardToc.scrollTop = sidebarScrollTop + 150
    }
    if (activePosition < 150) {
      $cardToc.scrollTop = sidebarScrollTop - 150
    }
  }

  document.addEventListener('pjax:send', function () {
    if ($('.toc').length) {
      tocbot.destroy();
    }
  });

  document.addEventListener('pjax:complete', function () {
    if ($('.toc').length) {
      tocbot.init(option);
      mobileTocClick();
    }
  });
  
  // 手机端toc按钮点击出现目录
  const mobileTocClick = function () {
    const $cardTocLayout = document.getElementsByClassName('side_toc')[0];
    const $cardToc = $cardTocLayout.getElementsByClassName('toc-content')[0];
    let right = '45px';
    if (window.innerWidth >= 551 && window.innerWidth <= 992) {
      right = '100px'
    }
    const mobileToc = {
      open: () => {
        $cardTocLayout.style.cssText = 'animation: toc-open .3s; opacity: 1; right: ' + right
      },

      close: () => {
        $cardTocLayout.style.animation = 'toc-close .2s'
        setTimeout(() => {
          $cardTocLayout.style.cssText = "opacity:''; animation: ''; right: ''"
        }, 100)
      }
    }
    document.getElementById('toc-mobile-btn').addEventListener('click', () => {
      if (window.getComputedStyle($cardTocLayout).getPropertyValue('opacity') === '0') mobileToc.open()
      else mobileToc.close()
    })

    $cardToc.addEventListener('click', (e) => {
      if (window.innerWidth < 992) { // 小于992px的时候
        mobileToc.close()
      }
    })
  }
</script>

<style>
  /* .is-position-fixed {
    position: sticky !important;
    top: 74px;
  }

  .toc-main ul {
    counter-reset: show-list;
  }

  .toc-main ul li::before {
    content: counter(item)".";
    display: block;
    position: absolute;
    left: 12px;
    top: 0;
  } */
</style>
 

<!-- 设置导航背景 -->
<script>
  let setHeaderClass = () => {
    const nav = $('#navHeader');
    const navTop = nav.outerHeight();
    const winTop = $(window).scrollTop();
    if(winTop > navTop) {
      nav.addClass('header-bg-color');
    }
    else {
      nav.removeClass('header-bg-color');
    }
  };

  let scrollCollect = () => {
    return bamboo.throttle(function (e) {
      setHeaderClass();
    }, 200)()
  }

  let initHeaderBg = () => {
    setHeaderClass();
  }

  setHeaderClass();
  window.addEventListener('scroll', scrollCollect);

  document.addEventListener('pjax:send', function () {
    window.removeEventListener('scroll', scrollCollect)
  })
  document.addEventListener('pjax:complete', function () {
    window.addEventListener('scroll', scrollCollect);
    setHeaderClass();
  })
</script> 

<!-- 渲染issues标签里的内容 -->
<script>
  function loadIssuesJS() {
    if ($(".post-detail").find(".issues-api").length == 0) {
      return;
    } 
    loadScript('/itblog/js/issues/index.js');
  };
  $(function () {
    loadIssuesJS();
  });
  document.addEventListener('pjax:complete', function () {
    if (typeof IssuesAPI == "undefined") {
      loadIssuesJS();
    }
  })
</script>

<!-- 渲染远程json加载的图片标签(getPhotoOnline)里的内容 -->
<script>
  function loadPhotoOnlineJS() {
    if ($(".post-detail").find(".getJsonPhoto-api").length == 0) {
      return;
    } 
    loadScript('/itblog/js/getPhotoOnline/index.js');
  };
  $(function () {
    loadPhotoOnlineJS();
  });
  document.addEventListener('pjax:complete', function () {
    if (typeof getPhotoJson == "undefined") {
      loadPhotoOnlineJS();
    }
  })
</script>

<!-- 渲染远程json加载的talk标签(getTalkOnline)里的内容 -->
<script>
  function loadTalkOnlineJS() {
    if ($(".post-detail").find(".getJsonTalk-api").length == 0) {
      return;
    } 
    loadScript('https://cdnjs.cloudflare.com/ajax/libs/waterfall.js/1.0.2/waterfall.min.js'); // 瀑布流插件，https://raphamorim.io/waterfall.js/
    loadScript('/itblog/js/getTalkOnline/index.js');
  };
  $(function () {
    loadTalkOnlineJS();
  });
  document.addEventListener('pjax:complete', function () {
    if (typeof getTalkJson == "undefined") {
      loadTalkOnlineJS();
    }
  })
</script>

<!-- 渲染远程json加载的site-card标签(getSiteOnline)里的内容 -->
<script>
  function loadSiteOnlineJS() {
    if ($(".post-detail").find(".getJsonSite-api").length == 0) {
      return;
    } 
    loadScript('/itblog/js/getSiteOnline/index.js');
  };
  $(function () {
    loadSiteOnlineJS();
  });
  document.addEventListener('pjax:complete', function () {
    if (typeof getSiteJson == "undefined") {
      loadSiteOnlineJS();
    }
  })
</script>

<!-- 输入框打字特效 -->
<!-- 输入框打字特效 -->

  <script src="/itblog/js/activate-power-mode.js"></script>
  <script>
    POWERMODE.colorful = true;  // 打开随机颜色特效
    POWERMODE.shake = false;    // 关闭输入框抖动
    document.body.addEventListener('input', POWERMODE);//监听打字事件
  </script>


<!-- markdown代码一键复制功能 -->

  <link rel="stylesheet" href="https://unpkg.com/v-plugs-ayu/lib/ayu.css">
  <script src="https://unpkg.com/v-plugs-ayu/lib/ayu.umd.min.js"></script>
  <script src="/itblog/js/clipboard/clipboard.min.js"></script>
  <div id="appCopy">
  </div>
  <script data-pjax>
    var vm = new Vue({
      el: '#appCopy',
      data: {
      },
      computed: {
      },
      mounted() {
        const that = this;
        var copy = 'copy';
        /* code */
        var initCopyCode = function () {
          var copyHtml = '';
          copyHtml += '<button class="btn-copy" data-clipboard-snippet="" style="position:absolute;top:0;right:0;z-index:1;">';
          copyHtml += '<i class="fas fa-copy"></i><span>' + copy + '</span>';
          copyHtml += '</button>';
          $(".post-detail pre").not('.gutter pre').wrap("<div class='codeBox' style='position:relative;width:100%;'></div>")
          $(".post-detail pre").not('.gutter pre').before(copyHtml);
          new ClipboardJS('.btn-copy', {
            target: function (trigger) {
              return trigger.nextElementSibling;
            }
          });
        }
        initCopyCode();
        $('.btn-copy').unbind('click').bind('click', function () {
          doSomething();
        })
        $(document).unbind('keypress').bind('keypress', function (e) {
          if (e.ctrlKey && e.keyCode == 67) {
            doSomething();
          }
        })

        function doSomething() {
          that.$notify({
            title: "成功",
            content: "代码已复制，请遵守相关授权协议。",
            type: 'success'
          })
        }
      },
      methods: {
      },
      created() { }
    })
  </script>
  

<!-- 图片懒加载 -->
<script defer src="https://unpkg.com/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script>
<script>
  // https://www.npmjs.com/package/vanilla-lazyload
  // Set the options globally
  // to make LazyLoad self-initialize
  window.lazyLoadOptions = {
    elements_selector: ".lazyload",
    threshold: 0
  };
  // Listen to the initialization event
  // and get the instance of LazyLoad
  window.addEventListener(
    "LazyLoad::Initialized",
    function (event) {
      window.lazyLoadInstance = event.detail.instance;
    },
    false
  );
  document.addEventListener('DOMContentLoaded', function () {
    lazyLoadInstance.update();
  });
  document.addEventListener('pjax:complete', function () {
    lazyLoadInstance.update();
  });
</script>


<!-- 卡片滚动动画 -->
   

<!-- 评论所需js -->

  
        <script type="text/javascript">
  var utteranceComment = {};

  function check_utterance() {
    let isDark = JSON.parse(localStorage.getItem('dark')) || JSON.parse('false');
    if (isDark) {
      utteranceComment.Theme = 'github-dark';
    } else {
      utteranceComment.Theme = 'github-light';
    }

    return document.getElementById("gitment-container");
  }
  comment_el = '#gitment-container';
  load_utterance = function () {
    if ($(comment_el).length) {
      // 匿名函数，防止污染全局变量
      const HEAD = check_utterance();

      var utterances = document.createElement('script');
      utterances.type = 'text/javascript';
      utterances.async = true;
      utterances.setAttribute('issue-term', 'pathname')
      utterances.setAttribute('theme', utteranceComment.Theme)
      utterances.setAttribute('repo', '')
      utterances.crossorigin = 'anonymous';
      utterances.src = 'https://utteranc.es/client.js';
      // content 是要插入评论的地方
      document.getElementById('gitment-container').appendChild(utterances);

    }
  }

  function dark_utterance() {
    const HEAD = check_utterance();
    if (!HEAD) return;
    const message = {
      type: 'set-theme',
      theme: utteranceComment.Theme
    };
    const utteranceIframe = document.querySelector('iframe');
    utteranceIframe.contentWindow.postMessage(message, 'https://utteranc.es');
  }

  $(document).ready(load_utterance);
  document.addEventListener('pjax:complete', function () {
    load_utterance();
  });

  $('.dark').click(function () {
    setTimeout(() => {
      dark_utterance();
    });
  })

</script>

<style>
  .utterances {
    max-width: inherit !important;
  }
</style>
      


<!-- 鼠标点击特效 -->
<!-- 爱心点击 -->

  
    <canvas class="fireworks" style="position: fixed;left: 0;top: 0;z-index: 999; pointer-events: none;" ></canvas>
    <script async src="//cdn.bootcss.com/animejs/2.2.0/anime.min.js"></script>
    <script async src="/itblog/js/cursor/explosion.min.js"></script>
  




  <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" data-pjax></script>


<!-- 轮播图标签 -->
<script>
  var bambooSwiperTag = {};
  function load_swiper() {
    if (!document.querySelectorAll(".post-swiper-container")[0]) return;
    loadCSS("https://unpkg.com/swiper@6/swiper-bundle.min.css")
    loadScript("https://unpkg.com/swiper@6/swiper-bundle.min.js").then(() => {
      pjax_swiper();
    });
  }

  load_swiper();

  function pjax_swiper() {
    bambooSwiperTag.swiper = new Swiper('.post-swiper-container', {
      slidesPerView: 'auto',
      spaceBetween: 8,
      centeredSlides: true,
      loop: true,
      autoplay: true ? {
        delay: 3000,
        stopOnLastSlide: false,
        disableOnInteraction: false,
      } : false,
      pagination: {
        el: '.swiper-pagination',
        clickable: true,
      },
      navigation: {
        nextEl: '.swiper-button-next',
        prevEl: '.swiper-button-prev',
      },
      on:{
        init: function(){
          swiperAnimateCache(this); //隐藏动画元素 
          swiperAnimate(this); //初始化完成开始动画
        }, 
        slideChangeTransitionEnd: function(){ 
          swiperAnimate(this); //每个slide切换结束时也运行当前slide动画
          //this.slides.eq(this.activeIndex).find('.ani').removeClass('ani'); 动画只展现一次，去除ani类名
        } 
      }
    });
  }

  document.addEventListener('pjax:complete', function () {
    if (!document.querySelectorAll(".post-swiper-container")[0]) return;
    if (typeof bambooSwiperTag.swiper === "undefined") {
      load_swiper();
    } else {
      pjax_swiper();
    }
  });
</script>
    <!-- pjax -->
    

<!-- pjax -->


  <script src="/itblog/js/pjax@0.2.8/index.js"></script>
  
    <div class="pjax-animate">
  
    <div class="loading-circle"><div id="loader-circle"></div></div>
    <script>
      window.ShowLoading = function() {
        $(".loading-circle").css("display", "block");
      };
      window.HideLoading = function() {
        $(".loading-circle").css("display", "none");
      }
    </script>
  
	<script>
    document.addEventListener('pjax:complete', function () {
      window.HideLoading();
    })
    document.addEventListener('pjax:send', function () {
      window.ShowLoading();
    })
    document.addEventListener('pjax:error', function () {
      window.HideLoading();
    })
	</script>
</div>

  

  <script>
    var pjax = new Pjax({
      elements: 'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([no-pjax])',   // 拦截正常带链接的 a 标签
      selectors: ["#pjax-container","title"],                                   // 根据实际需要确认重载区域
      cacheBust: false,   // url 地址追加时间戳，用以避免浏览器缓存
      timeout: 5000
    });

    document.addEventListener('pjax:send', function (e) {

      try {
        var currentUrl = window.location.pathname;
        var targetUrl = e.triggerElement.href;
        var banUrl = [""];
        if (banUrl[0] != "") {
          banUrl.forEach(item => {
            if(currentUrl.indexOf(item) != -1 || targetUrl.indexOf(item) != -1) {
              window.location.href = targetUrl;
            }
          });
        }
      } catch (error) {}

      $(window).unbind('resize');
      $(window).unbind('scroll');
      $(document).unbind('scroll');
      $(document).unbind('click');
      $('body').unbind('click');

    })
    
    document.addEventListener('pjax:complete', function () {
      $('script[data-pjax], .pjax-reload script').each(function () {
        $(this).parent().append($(this).remove());
      });
    });

    document.addEventListener('pjax:error', function (e) {
      window.location.href = e.triggerElement.href;
    })
    
    // 刷新不从顶部开始
    document.addEventListener("DOMContentLoaded", function () {
      history.scrollRestoration = 'auto';
    })
  </script>



  </body>
</html>